package com.lee.auth.security.context;

import com.lee.auth.security.authority.Authority;
import com.lee.common.exception.CustomException;

import static com.lee.auth.security.context.AuthContextHolder.getAuthContext;
import static java.lang.Long.MIN_VALUE;

/**
 * @author Lee HN
 * @date 2021/3/31 16:17
 */
public final class AuthContextVerifier {

    /**
     * 对于短数组而言 直接循环匹配效率更高 构造set效率反而低
     *
     * @param authority
     * @return
     */
    public static void hasAuthority(Authority authority) {
        AuthContext authContext = isAuthenticated();
        int[] authorities0 = authContext.authorities;
        if (authorities0 != null)
            for (int s : authorities0)
                if (authority.code == s) return;
        throw CustomException.AUTHORITY_DENIED_EXC;
    }

    public static void hasAnyAuthority(Authority... authorities) {
        AuthContext authContext = isAuthenticated();
        int[] authorities0 = authContext.authorities;
        if (authorities0 != null)
            for (int s : authorities0)
                for (Authority authority : authorities)
                    if (authority.code == s) return;
        throw CustomException.AUTHORITY_DENIED_EXC;
    }

    public static void hasAllAuthority(Authority... authorities) {
        AuthContext authContext = isAuthenticated();
        int[] authorities0 = authContext.authorities;
        if (authorities0 != null) {
            int length = authorities.length;
            int i = 0;
            for (int s : authorities0)
                for (Authority authority : authorities)
                    if (authority.code == s) i += 1;
            if (i == length) return;
        }
        throw CustomException.AUTHORITY_DENIED_EXC;
    }

    public static void notHasAuthority(Authority authority) {
        AuthContext authContext = isAuthenticated();
        int[] authorities0 = authContext.authorities;
        if (authorities0 != null)
            for (int s : authorities0)
                if (authority.code == s)
                    throw CustomException.AUTHORITY_DENIED_EXC;
    }

    public static void permitAll() { }

    public static void denyAll() {
        throw CustomException.AUTHORITY_DENIED_EXC;
    }

    public static void isAnonymous() {
        if (getAuthContext() != AuthContext.ANONYMOUS)
            throw CustomException.AUTHORITY_DENIED_EXC;
    }

    public static AuthContext isAuthenticated() {
        AuthContext authContext = getAuthContext();
        if (authContext.expired)
            throw CustomException.EXPIRED_CREDENTIAL_EXC;
        if (authContext.userId == MIN_VALUE)
            throw CustomException.NO_AUTHENTICATED_EXC;
        return authContext;
    }

}
